package org.oschina.api.upload.service;

import java.io.File;
import java.io.IOException;

import org.apache.commons.io.FileUtils;
import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang.RandomStringUtils;
import org.apache.commons.lang.StringUtils;
import org.oschina.Message;
import org.oschina.Module;
import org.oschina.ResultUtil;
import org.oschina.api.BaseService;
import org.oschina.api.upload.UploadConfigType;
import org.oschina.api.upload.vo.UploadConfigVo;
import org.oschina.bean.Result;
import org.oschina.config.Config;
import org.oschina.helper.ApplicationHelper;
import org.oschina.security.annotation.Require;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class UploadService extends BaseService {

	private final static Logger logger=LoggerFactory.getLogger(UploadService.class);
	
	@Autowired
	private UploadConfigService uploadConfigService;
	@Autowired
	private UploadRecordService uploadRecordService;
	
	/**
	 * 普通上传
	 * @param file
	 * @return
	 */
	@Require
	public Result simple(File file)
	{
		return _baseUpload(UploadConfigType.SIMPLE,file);
	}
	
	/**
	 * 上传头像
	 * @param file
	 * @return
	 */
	@Require
	public Result user_headphoto(File file)
	{
		return _baseUpload(UploadConfigType.USER_HEADPHOTO,file);
	}
	
	/**
	 * 上传软件图标
	 * @param file
	 * @return
	 */
	@Require(authorization=Module.MODULE_13)
	public Result software_icon(File file)
	{
		return _baseUpload(UploadConfigType.SOFTWARE_ICON,file);
	}

	/**
	 * 上传
	 * @param configId
	 * @param file
	 * @return
	 */
	public Result _baseUpload(int configId,File file)
	{
		return _baseUpload(configId,true,true,file);
	}
	
	/**
	 * 上传
	 * @param configId
	 * @param isChangeName
	 * @param save
	 * @param file
	 * @return
	 */
	public Result _baseUpload(int configId,boolean isChangeName,boolean save,File file)
	{
		if(file==null)
			return ResultUtil.getFailure(Message.ERROR_DATA_ERROR);
		
		UploadConfigVo uploadConfig=uploadConfigService._findVoById(configId);
		if(uploadConfig==null)
		{
			logger.error("ID为 '{}' 的上传配置数据错误",configId);
			return ResultUtil.getFailure(Message.ERROR_APP_ERROR);
		}
		
		return _baseUpload(uploadConfig.getPath(),uploadConfig.getType(),uploadConfig.getSize(),isChangeName,save,file);
	}
	
	/**
	 * 上传
	 * @param path
	 * @param type
	 * @param size
	 * @param isChangeName
	 * @param save
	 * @param file
	 * @return
	 */
	public Result _baseUpload(String path,String type,int size,boolean isChangeName,boolean save,File file)
	{
		int suffixIndex=file.getName().indexOf(".");
		String fileType=(suffixIndex==-1?"":StringUtils.substring(file.getName(), suffixIndex+1, file.getName().length()));
		
		if(!StringUtils.isBlank(type))
		{
			String types[]=StringUtils.split(type,",");
			//类型判断
			for(int i=0;i<types.length;i++)
			{
				if(fileType.equals(types[i]))
					break;
				
				if(i==types.length-1)
					return ResultUtil.getFailure(Message.get(Message.UPLOAD_ERROR_TYPE_ERROR, ArrayUtils.toString(type)));
			}
			
		}
		
		//大小判断
		int size_mb=(int) (file.length()/1024/1024);
		if(size_mb>size)
			return ResultUtil.getFailure(Message.get(Message.UPLOAD_ERROR_OUT_OF_SIZE, size));
		
		String newName=(isChangeName?getRandomName():(suffixIndex==-1?file.getName():file.getName().substring(0,suffixIndex)));
		String newFilePath=path+newName+"."+fileType;
		File serverPath=new File(ApplicationHelper.getServletContext().getRealPath("/")+newFilePath);
		
		if(save)
		{
			try
			{
				FileUtils.copyFile(file, serverPath);
				uploadRecordService.create(newName,path,file.length(),fileType);
			}
			catch (IOException e)
			{
				logger.error("上传失败:",e);
				return ResultUtil.getFailure(Message.ERROR_APP_ERROR);
			}
		}
		return ResultUtil.getSuccess(Config.HOST_ROOT_PATH+newFilePath);
	}
	
	/**
	 * 返回随机名称
	 * @return
	 */
	private String getRandomName()
	{
		return RandomStringUtils.randomAlphabetic(30);
	}
}